package com.itzmn.java.javase.collections;


import java.util.Arrays;
import java.util.Collection;

/**
 * @Author: 张梦楠
 * @Date: 2018/12/5 19:33
 * 简书：https://www.jianshu.com/u/d611be10d1a6
 * 码云：https://gitee.com/zhangqiye
 * @Description:  自定义的ArrayList
 */
public class QiYeArrayList<T> {


    /**
     * 存放数据的数组
     */
    private Object[] data;
    /**
     * 空数组
     */
    private Object[] empty = {};
    /**
     * 默认构造器的空数组，在添加的时候，判断，进行不同的构造
     */
    private Object[] default_empty = {};

    /**
     * 集合的数据量
     */
    private int size;

    private static final int INITSIZE = 10;

    public QiYeArrayList(){

        this.data = this.default_empty;
    }
    public QiYeArrayList(int init) throws Exception {

        if (init < 0){
            throw new IllegalArgumentException("初始化参数错误: "+
                    init);
        }else {
            this.data = new Object[init];
        }
    }

    public Object[] toArray(){
        return Arrays.copyOf(data,size);
    }
    public int size(){
        return size;
    }

    public boolean add(Object o){
        // 1. 得到需要的数组
        checkOldArray(data,size+1);
        // 2. 将数据放在数组中
        data[size++] = o;

        return true;
    }

    private void checkOldArray(Object[] data, int i) {

       // 2.返回需要的数组长度
        int arrayLength = getArrayLength(data, i);
        //3. 对校验两个数组是否匹配
        checkOldArrayIsOK(arrayLength);
    }

    private void checkOldArrayIsOK(int arrayLength) {
        if (arrayLength - data.length > 0){
            // 需要的数组大于现在的数组长度，需要扩容
            grow(arrayLength);
        }
    }

    private void grow(int arrayLength) {

        int oldLength = data.length;
        int newLength = oldLength + oldLength >> 1;
        // 如果扩容之后还是不够，则将数组指定为需要的数组长度
        if (arrayLength > newLength){
            newLength = arrayLength;
        }

        // 将原有数据拷贝过来，生成新的数组，
        data = Arrays.copyOf(data, newLength);

    }

    private int getArrayLength(Object[] data,int i) {

        return data == default_empty ? INITSIZE:i;
    }


    public boolean add(int index, Object o){
        checkIndex(index);
        // 1.得到需要的数组
        checkOldArray(data,size+1);
        // 2. 将原数据进行挪动  0 1 2 3 4    5
        System.arraycopy(data,index,data,index+1,size-index);

        // 3.添加新数据
        data[index] = o;
        size++;
        return true;
    }

    private void checkIndex(int index) {
        if (index < 0 || index > size){
            throw new IndexOutOfBoundsException("下标越界了index:"+index+",size:"+size);
        }
    }

    public boolean addAll(Collection c){
        Object[] objects = c.toArray();
        int length = objects.length;
        if (length == 0){
            return true;
        }
        // 1.得到需要的数组
        checkOldArray(data,size+length);
        // 2.对数组进行数据的挪动
        System.arraycopy(objects,0,data,size,length);
        size += length;
        return true;
    }

    public Object get(int index){

        checkIndex(index);
        Object datum = data[index];
        return datum;
    }
    public Object set(int index,Object o){
        checkIndex(index);

        Object datum = data[index];
        data[index] = o;
        return datum;
    }

    public Object remove(int index){
        checkIndex(index);
        Object datum = data[index];
        int moveSize = size - index - 1;
        if (moveSize > 0){
            // 1.对数据进行拷贝
            System.arraycopy(data,index+1,data,index,size-index-1);
        }

        data[--size] = null;
        return datum;
    }
    public boolean remove(Object o){
        if (null == o){
            for (int i=0;i<size;i++){
                if (data[i] == null){
                    removeIndex(i);
                    return true;
                }
            }
        }else {
            for (int i=0;i<size;i++){
                if (data[i] .equals(o)){
                    removeIndex(i);
                    return true;
                }
            }
        }
        return false;
    }

    private void removeIndex(int index) {
        checkIndex(index);
        // 1. 对数据进行拷贝
        int moveSize = size - index - 1;
        if (moveSize > 0){
            // 1.对数据进行拷贝
            System.arraycopy(data,index+1,data,index,size-index-1);
        }

        data[--size] = null;
    }

}
